/*******************************************************************************
 * Copyright 2013 BSE TEAM
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * PROJECT NAME	: bse-baseinfo-api
 * 
 * FILE PATH        	: src/main/java/com/deppon/foss/module/frameworkimpl/shared/domain/Cookie.java
 * 
 * FILE NAME        	: Cookie.java
 * 
 * AUTHOR			: FOSS综合管理开发组
 * 
 * HOME PAGE		:  http://www.deppon.com
 * 
 * COPYRIGHT		: Copyright (c) 2013  Deppon All Rights Reserved.
 ******************************************************************************/
package com.hn658.base.util.auth;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;

import com.hn658.base.util.constants.BaseContants;
import com.hn658.base.util.exception.AuthCookieException;
import com.hn658.base.util.util.TokenMarshal;
import com.hn658.framework.logging.Logger;
import com.hn658.framework.logging.LoggerFactory;
import com.hn658.framework.logging.enums.LogCategory;
import com.hn658.framework.shared.constants.CommonConstants;
import com.hn658.framework.shared.exception.UserNotLoginException;

/**
 * 
 * Cookie操作类 主要功能： 1.生成Cookie {@link #saveCookie()} 2.Cookie数据到Session
 * <p style="display:none">
 * modifyRecord
 * </p>
 * <p style="display:none">
 * version:V1.0,author:053990,date:2013-12-3 下午3:45:54
 * </p>
 * 
 * @author ztjie
 * @date 2013-12-3 下午3:45:54
 * @since
 * @version
 */
public final class AuthCookieEditor {

	private static final Logger LOG = LoggerFactory
			.getLogger(AuthCookieEditor.class);
	private AuthCookieEditor() {
	}

	private static AuthCookieEditor cookie;

	public static AuthCookieEditor getInstance() {
		if (cookie == null) {
			cookie = new AuthCookieEditor();
		}
		return cookie;
	}

	/**
	 * 获取Token字符串
	 * 
	 * @author ztjie
	 * @date 2012-12-20 下午3:37:53
	 * @return
	 * @see
	 */
	public static String getTokenParam(HttpSession session) {
		String uid = (String) session.getAttribute(CommonConstants.SERVICE_REQUEST_HEADER_UID);
		String authkey = (String) session.getAttribute(CommonConstants.SERVICE_REQUEST_HEADER_AUTHKEY);
		Token token = new Token(uid, authkey, session.getMaxInactiveInterval());
		return TokenMarshal.marshal(token);
	}

	/**
	 * 保存cookie 主要功能： 1.根据session重新生成cookie 2.修改cookie的时间戳
	 * 
	 * @author ztjie
	 * @date 2012-11-28 下午8:57:44
	 * @param token
	 * @param response
	 * @see
	 */
	public static void saveCookie(HttpServletRequest request, HttpServletResponse response) {

		String tokenParam = getTokenParam(request.getSession());
		try {
			tokenParam = URLEncoder.encode(tokenParam, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOG.error(LogCategory.SYSTEM, "cookie encode error", e);
			throw new AuthCookieException(AuthCookieException.CookieEncodeError);
		}
		Cookie cookie = getCookie(request);
		if (cookie != null) {
			// 修改cookie时间戳
			cookie.setValue(tokenParam);
		} else {
			// 重新new一个Cookie
			cookie = new Cookie(BaseContants.TOKEN_NAME, tokenParam);
		}
		cookie.setPath("/");// 同一个域名所有url cookie共享
		// cookie.setMaxAge(5*60);不写入磁盘，只写入内存，只有在当前页面有用,浏览器关闭立即失效
		cookie.setDomain(BaseContants.SERVICE_SITE_DOMIN);
		response.addCookie(cookie);
	}

	/**
	 * 失效Cookie
	 * 
	 * @author ztjie
	 * @date 2012-11-30 上午10:12:24
	 * @see
	 */
	public static void invalidateCookie(HttpServletRequest request, HttpServletResponse response) {
		// 失效掉token的cookie
		Cookie cookie_token = getCookie(request);
		if (cookie_token != null) {
			cookie_token.setMaxAge(0);// 设置为0立即删除
			cookie_token.setDomain(BaseContants.SERVICE_SITE_DOMIN);
			response.addCookie(cookie_token);
		}
		Cookie cookie_jsession = getCookie(request, CommonConstants.JSESSIONID);
		if (cookie_jsession != null) {
			cookie_jsession.setMaxAge(0);// 设置为0立即删除
			response.addCookie(cookie_jsession);
		}
	}

	/**
	 * 获取HttpCookie对象,token对应的cookie
	 * 
	 * @author ztjie
	 * @date 2012-12-6 上午9:49:55
	 * @return
	 * @see
	 */
	public static Cookie getCookie(HttpServletRequest request) {
		return getCookie(request, BaseContants.TOKEN_NAME);
	}
	
	/**
	 * 获取HttpCookie对象,token对应的cookie值
	 * 
	 * @author ztjie
	 * @date 2012-12-6 上午9:49:55
	 * @return
	 * @see
	 */
	public static String getCookieValue(HttpServletRequest request) {
		Cookie cookie =  getCookie(request, BaseContants.TOKEN_NAME);
		if(cookie!=null){
			return cookie.getValue();
		}
		return null;
	}

	/**
	 * 获取HttpCookie对象,根据传入的cookie的name值获取, 参数可以通过ServicesContants获取
	 * 
	 * @author ztjie
	 * @date 2012-12-13 上午11:54:31
	 * @param name
	 * @return
	 * @see
	 */
	public static Cookie getCookie(HttpServletRequest request, String name) {
		if (StringUtils.isBlank(name)) {
			return null;
		}
		Cookie[] cookies = request.getCookies();
		if (cookies != null && cookies.length > 0) {
			for (int i = 0; i < cookies.length; i++) {
				if (name.equals(cookies[i].getName())) {
					return cookies[i];
				}
			}
		}
		return null;
	}

	/**
	 * Cookie数据到Session 主要功能： 1.Cookie不存在，Throw UserNotLoginException异常
	 * 2.Cookie存在，赋值到Session
	 * 
	 * @author ztjie
	 * @date 2012-11-30 上午8:31:15
	 * @see
	 */
	public static void cookieToSession(Cookie cookie, HttpSession session) throws UserNotLoginException{
		if (cookie != null) {
			String paramToken = cookie.getValue();
			LOG.debug(LogCategory.SYSTEM, "cookieToSession paramToken = "+paramToken);
			if (StringUtils.isBlank(paramToken)) {
				throw new UserNotLoginException();// 用户未登录
			} else {
				try {
					paramToken = URLDecoder.decode(paramToken, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					LOG.error(LogCategory.SYSTEM, "cookie encode error", e);
					throw new AuthCookieException(AuthCookieException.CookieEncodeError);
				}
				Token token = TokenMarshal.unMarshal(paramToken);
				LOG.debug(LogCategory.SYSTEM, "cookieToSession token = "+token);
				if (token != null && !token.expired()) {
					AuthCookieEditor.getInstance().tokenToSession(session, token);
				} else {
					throw new UserNotLoginException();// 用户未登录
				}
			}
		} else {
			throw new UserNotLoginException();// 用户未登录
		}
	}
	
	/**
	 * Cookie数据到Session 主要功能： 1.Cookie不存在，Throw UserNotLoginException异常
	 * 2.Cookie存在，赋值到Session
	 * 
	 * @author ztjie
	 * @date 2012-11-30 上午8:31:15
	 * @see
	 */
	public static void cookieToSessionNoValidate(Cookie cookie, HttpSession session) {
		if (cookie != null) {
			String paramToken = cookie.getValue();
			if (StringUtils.isBlank(paramToken)) {
				return;
			} else {
				Token token = TokenMarshal.unMarshal(paramToken);
				AuthCookieEditor.getInstance().tokenToSession(session, token);
			}
		}
	}

	/**
	 * token的内容复制到session中
	 * 
	 * @author ztjie
	 * @date 2012-11-29 上午9:12:20
	 * @param token
	 * @see
	 */
	private void tokenToSession(HttpSession session, Token token) {
		session.setAttribute(CommonConstants.SERVICE_REQUEST_HEADER_UID,
				token.getUid());
		session.setAttribute(CommonConstants.SERVICE_REQUEST_HEADER_AUTHKEY,
				token.getAuthkey());
	}

}
